#ifdef WIN32
#	include "IocpService.h"
#elif defined(LINUX)
#	include "EpollService.h"
#endif
#include "TcpServer.h"
#include "MacroTools.h"
#include "../SockException.h"
#include "../Timer.h"
#include "Socket.h"
#include <assert.h>

DEF_BEG_LIBTOOLS

CTcpServer::CTcpServer(bool isWriteLog) :CTcpBase(isWriteLog)
{
#ifdef WIN32
	_service.Reset(new CIocpService(&IoCompleteFunc));
#elif defined(LINUX)
	_service.Reset(new CEpollService(&IoCompleteFunc));
#endif
	if (isWriteLog)
		_service->SetWriteLog(true);
}

CTcpServer::~CTcpServer()
{

}

CIoPortService* CTcpServer::GetIoPortService()
{
	return dynamic_cast<CIoPortService*>(_service.Get());
}

CSockError CTcpServer::Init(CSocket& sock, bool isServer/* = false*/)
{
	if (!_service->IsInit()) {
		throw CSockException(CSockError(CSockError::UNINIT).GetErrorMsg().c_str());
	}

	sock.SetService(this);
	return _service->Init(sock, isServer);
}

void CTcpServer::AsyncAccept(CSocket& svrSock, CSocket& cliSock, const SharedPtr<HandleBase>& func, void* invoker /* = NullPtr */)
{
	if (!_service->IsInit())
	{
		CSockError ec;
		ec.SetError(CSockError::UNINIT);
		throw CSockException(ec.GetErrorMsg().c_str());
	}
	else {
		_service->PostAcceptEx(svrSock, cliSock, func, invoker);
	}
}

void CTcpServer::AsyncRead(CSocket& sock, const CStreamIteator& buff, const SharedPtr<HandleBase>& func, void* invoker /* = NullPtr */)
{
	if (!_service->IsInit())
	{
		CSockError ec;
		ec.SetError(CSockError::UNINIT);
		throw CSockException(ec.GetErrorMsg().c_str());
	}
	else
	{
		_service->DeliveryRecv(sock, const_cast<char*>(buff.cbegin()), const_cast<char*>(buff.cend()), NullPtr, func, invoker);
	}
}

void CTcpServer::AsyncSend(CSocket& sock, const CStreamIteator& buff, const SharedPtr<HandleBase>& func, void* invoker /* = NullPtr */)
{
	if (!_service->IsInit())
	{
		CSockError ec;
		ec.SetError(CSockError::UNINIT);
		throw CSockException(ec.GetErrorMsg().c_str());
	}
	else
	{
		_service->DeliveryWrite(sock, buff.cbegin(), buff.cend(), NullPtr, func, invoker);
	}
}

void CTcpServer::Post(const SharedPtr<HandleBase>& func, void* invoker /* = NullPtr */)
{
	if (!_service->IsInit())
	{
		CSockError ec;
		ec.SetError(CSockError::UNINIT);
		throw CSockException(ec.GetErrorMsg().c_str());
	}
	else
	{
		_service->Post(func, invoker);
	}
}

bool CTcpServer::Run()
{
	return _service->Run();
}

bool CTcpServer::Run_One()
{
	return _service->Run_One();
}

void CTcpServer::NotifyStop()
{
	 _service->NotifyStop();
}

bool CTcpServer::IsStop() const
{
	return _service->IsStop();
}

void CTcpServer::WaitServerStop()
{
	_service->NotifyStop();
	_service->Shutdown();
}

void CTcpServer::DelTimer(CTimerBase& timer)
{
	_service->DelTimer(*timer.GetTimerInfo());
}

void CTcpServer::SetTimer(CTimerBase& timer)
{
	_service->SetTimer(*timer.GetTimerInfo());
}

bool CTcpServer::UpdateTimer(CTimerBase& timer)
{
	return _service->UpdateTimer(*timer.GetTimerInfo());
}

DWORD CTcpServer::IoCompleteFunc(OVERLAPPED_EX* oved)
{
	DWORD dwRet = 0;
	SharedPtr<HandleBase> handle;
	handle.Swap(oved->handle);

	if (oved->sockStatus == SOCKETSTATUS::ACCEPTED)
	{
		dwRet = (*handle)(oved->sockError, oved->invoker);
	}
	else if (oved->sockStatus == SOCKETSTATUS::RECVED)
	{
		dwRet = (*handle)(oved->wsaPtr.buf, oved->dwRead, oved->sockError, oved->invoker);
	}
	else if (oved->sockStatus == SOCKETSTATUS::SENDED)
	{
		dwRet = (*handle)(oved->wsaPtr.buf, oved->dwWrite, oved->sockError, oved->invoker);
	}
	else if (oved->sockStatus == SOCKETSTATUS::POST)
	{
		dwRet = (*handle)(oved->invoker);
	}
	else
	{
		assert(dwRet);
	}

	return dwRet;
}


DEF_END_LIBTOOLS